1

Sample 50 points that fall within the boundaries of the city of Cologne. You will find the shapefile in the ./data folder.
The shapefile is no raster file, so that you would need the sf::read_sf() function to load the data. Sampling is straightforward: Apply the sf::st_sample to the loaded shapefile, but make sure to apply the sf::st_as_sf() function afterward to receive a full-fledged data table (with a geometry column only).
library(dplyr)

cologne <-
  sf::read_sf("./data/cologne.shp")

cologne_50_points <-
  cologne %>% 
  sf::st_sample(50) %>% 
  sf::st_as_sf()

2

Create a new raster layer comprising Cologne’s immigrant rates based on the raster layers from the previous exercises.
You would need the immigrants_cologne.tif and inhabitants_cologne.tif files in the ./data/ folder.
library(terra)

immigrant_rates <-
  terra::rast("./data/immigrants_cologne.tif") * 100 /
  terra::rast("./data/inhabitants_cologne.tif")

3

Extract the immigrant rate value at each position of the previously sampled points as a vector. What is your observation?
Remember that the German Census 2011 data are relatively sparse due to some severe data protection measures.
immigrant_rates_at_point <-
  terra::extract(immigrant_rates, terra::vect(cologne_50_points))

# There may be a lot of missing values.

4

Use an adequate method of raster extraction to gather information in the geographic surrounding of a point. What is your observation now?
Assume that people move in a 500 meters radius around their location. Thus, extracting information on buffers of 500 meters around the points might be interesting using the option sf::st_buffer() function. In that case, you should also set a descriptive statistics function, e.g., with the option fun = mean and its helpful companion option to consider missing values na.rm = TRUE.
immigrant_rates_500m_buffer <-
  terra::extract(
    immigrant_rates, 
    cologne_50_points %>% 
      sf::st_buffer(500) %>% 
      terra::vect(), 
    fun = mean,
    na.rm = TRUE
    )